package com.dyna.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dyna.constants.ModuleErrorCodeConstants;
import com.dyna.core.exception.CustomException;
import com.dyna.core.utils.ObjectUtil;
import com.dyna.domain.resp.PageResult;
import com.dyna.enums.CommonStatusEnum;
import com.dyna.foundation.domain.entity.SysTenant;
import com.dyna.foundation.domain.entity.SysTenantPackage;
import com.dyna.foundation.domain.form.SysTenantPackageSaveForm;
import com.dyna.foundation.domain.req.SysTenantPackagePageReq;
import com.dyna.mapper.SysTenantPackageMapper;
import com.dyna.service.SysTenantPackageService;
import com.dyna.service.SysTenantService;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.List;

/**
 * 租户 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Slf4j
public class SysTenantPackageServiceImpl
        extends ServiceImpl<SysTenantPackageMapper, SysTenantPackage>
        implements SysTenantPackageService
{

    @Resource
    @Lazy // 避免循环依赖的报错
    private SysTenantService tenantService;

    @Override
    public Long createTenantPackage(SysTenantPackageSaveForm createReqVO) {
        // 校验套餐名是否重复
        validateTenantPackageNameUnique(null, createReqVO.getName());
        // 插入
        SysTenantPackage tenantPackage = BeanUtil.toBean(createReqVO, SysTenantPackage.class);
        baseMapper.insert(tenantPackage);
        // 返回
        return tenantPackage.getId();
    }

    @VisibleForTesting
    void validateTenantPackageNameUnique(Long id, String name) {
        if (StrUtil.isBlank(name)) {
            return;
        }
        SysTenantPackage tenantPackage = baseMapper.selectByName(name);
        if (tenantPackage == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (ObjectUtil.isNull(id) || !ObjectUtil.equals(tenantPackage.getId(),id)) {
            throw new CustomException(ModuleErrorCodeConstants.TENANT_PACKAGE_NAME_DUPLICATE.getMsg());
        }
    }

    @Override
    @DSTransactional // 多数据源，使用 @DSTransactional 保证本地事务，以及数据源的切换
    public void updateTenantPackage(SysTenantPackageSaveForm updateReqVO) {
        // 校验存在
        SysTenantPackage tenantPackage = validateTenantPackageExists(updateReqVO.getId());
        // 校验套餐名是否重复
        validateTenantPackageNameUnique(updateReqVO.getId(), updateReqVO.getName());
        // 更新
        SysTenantPackage updateObj = BeanUtil.toBean(updateReqVO, SysTenantPackage.class);
        baseMapper.updateById(updateObj);
        // 如果菜单发生变化，则修改每个租户的菜单
        if (!CollUtil.isEqualList(tenantPackage.getMenuIds(), updateReqVO.getMenuIds())) {
            List<SysTenant> tenants = tenantService.getTenantListByPackageId(tenantPackage.getId());
            tenants.forEach(tenant -> tenantService.updateTenantRoleMenu(tenant.getId(), updateReqVO.getMenuIds()));
        }
    }

    private SysTenantPackage validateTenantPackageExists(Long id) {
        SysTenantPackage tenantPackage = baseMapper.selectById(id);
        if (tenantPackage == null) {
            throw new CustomException(ModuleErrorCodeConstants.TENANT_PACKAGE_NOT_EXISTS.getMsg());
        }
        return tenantPackage;
    }

    @Override
    public List<SysTenantPackage> getTenantPackageListByStatus(Integer status) {
        return baseMapper.selectListByStatus(status);
    }

    @Override
    public SysTenantPackage validTenantPackage(Long id) {
        SysTenantPackage tenantPackage = baseMapper.selectById(id);
        if (tenantPackage == null) {
            throw new CustomException(ModuleErrorCodeConstants.TENANT_PACKAGE_NOT_EXISTS.getMsg());
        }
        if (tenantPackage.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) {
            throw new CustomException(StrUtil.format(ModuleErrorCodeConstants.TENANT_PACKAGE_DISABLE.getMsg(),tenantPackage.getName()));
        }
        return tenantPackage;
    }

    @Override
    public void deleteTenantPackage(Long id) {
        // 校验存在
        validateTenantPackageExists(id);
        // 校验正在使用
        validateTenantUsed(id);
        // 删除
        baseMapper.deleteById(id);
    }

    private void validateTenantUsed(Long id) {
        if (tenantService.getTenantCountByPackageId(id) > 0) {
            throw new CustomException(ModuleErrorCodeConstants.TENANT_PACKAGE_USED.getMsg());
        }
    }

    @Override
    public SysTenantPackage getTenantPackage(Long id) {
        return baseMapper.selectById(id);
    }

    @Override
    public PageResult<SysTenantPackage> getTenantPackagePage(SysTenantPackagePageReq pageReqVO) {
        return baseMapper.selectPage(pageReqVO);
    }


}
